package com.meme.editor.property;

import java.util.Vector;
import java.util.Hashtable;

import com.meme.editor.EntityObject;

import org.apache.log4j.Logger;

public class PropertyGroupSet 
{
	static Logger logger = Logger.getLogger (PropertyGroupSet.class);
	{
		logger.setLevel (org.apache.log4j.Level.ERROR);
	}
	
	EntityObject mOwner;
	
	Vector<PropertyGroup>            mPropertyGroups = new Vector<PropertyGroup> ();
	Hashtable<String, PropertyGroup> mLookupTable    = new Hashtable<String, PropertyGroup> ();
	
	
	public PropertyGroupSet (EntityObject owner)
	{
		mOwner = owner;
	}
	
	public EntityObject getOwner ()
	{
		return mOwner;
	}
	
	public void createPropertyGroup (String name)
	{
		createPropertyGroup (name, null);
	}
	
	public void createPropertyGroup (String name, String label)
	{
		logger.assertLog (name != null, "Group key can't be null." );
		
		if ( mLookupTable.get (name) == null )
		{
			PropertyGroup group = new PropertyGroup (this, name, label);
			mPropertyGroups.add (group);
			mLookupTable.put (name, group);
		}
		else
		{
			logger.warn ("Group [" + name + "] already exists.");
		}
	}
	
	public void removePropertyGroup (String name)
	{
		
		
		PropertyGroup group = mLookupTable.get (name);
		if ( group != null )
		{
			mLookupTable.remove(name);
			mPropertyGroups.remove ( group );
		}
		else
		{
			logger.warn ("Group [" + name + "] doesn't exist, how to remove?");
		}
	}
	
	// PropertyGroup is private
	// maybe the Property class should also be private, but that will make some inconvenience
//	public PropertyGroup getPropertyGroup ()
//	{
//		return null;
//	}
	
	public int getPropertyGroupsCont ()
	{
		logger.assertLog ( mPropertyGroups.size() == mLookupTable.size(), "The sizes of mPropertyGroups and mLookupTable are not matched." );

		return mPropertyGroups.size();
	}
	
	protected PropertyGroup getPropertyGroup (int i)
	{
		logger.assertLog ( mPropertyGroups.size() > i && i >= 0, "Out of boundary." );
		
		return mPropertyGroups.elementAt (i);
	}
	
	protected PropertyGroup getPropertyGroup (String name)
	{
		logger.assertLog (name != null, "Group key can't be null." );
		
		PropertyGroup group = mLookupTable.get (name);
		
		if ( group != null )
			return group;
		else
		{
			logger.warn ("Group [" + name + "] doesn't exist." );
			return null;
		}		
	}
	
	
	
	public String getPropertyGroupName (int i)
	{
		return getPropertyGroup (i).getName();
	}
	
	public String getPropertyGroupName (Property property)
	{
		return property.getGroup().getName();
	}
	
	public String getPropertyGroupLabel (int i)
	{
		return getPropertyGroup (i).getLabel();
	}
	
	public String getPropertyGroupLabel (String key)
	{
		return getPropertyGroup (key).getLabel();
	}
	
	public int getPropertiesCountInGroup (int i)
	{	
		return getPropertyGroup (i).getPropertiesCount ();
	}
	
	public int getPropertiesCountInGroup (String name)
	{
		return getPropertyGroup (name).getPropertiesCount();
	}
	
	public Property getPropertyInGroup (int iGroup, int iProperty)
	{
		return getPropertyGroup (iGroup).getProperty(iProperty);
	}
	
	public Property getPropertyInGroup (String groupName, int iProperty)
	{
		return getPropertyGroup (groupName).getProperty(iProperty);
	}
	
	public Property getPropertyInGroup (int iGroup, String propertyName)
	{
		return getPropertyGroup (iGroup).getProperty(propertyName);
	}
	
	public Property getPropertyInGroup (String groupName, String propertyName)
	{
		if( groupName == null )
			return getProperty (propertyName);
		
		PropertyGroup group = getPropertyGroup (groupName);
		if (group == null)
			return null;
		
		return group.getProperty(propertyName);
	}
	
	public Property removeProperty (int iGroup, int iProperty)
	{
		return getPropertyGroup (iGroup).removeProperty(iProperty);
	}

	public Property removeProperty (String groupName, int iProperty)
	{
		return getPropertyGroup (groupName).removeProperty(iProperty);
	}

	public Property removeProperty (int iGroup, String propertyName)
	{
		return getPropertyGroup (iGroup).removeProperty(propertyName);
	}

	public Property removeProperty (String groupName, String propertyName)
	{
		if ( groupName == null )
			return removeProperty (propertyName);
		
		return getPropertyGroup (groupName).removeProperty (propertyName);
	}	
	
//-------------------------------------------------------------------------------------------
	
	public Property createProperty (String groupName, String propertyName, String valueType)
	{
		if ( getPropertyGroup (groupName) == null )
		{
			logger.warn ("Group [" + groupName + "] has not been created yet. Create it with label same as name");
			
			createPropertyGroup (groupName, null);
		}
		
		return getPropertyGroup (groupName).createProperty(propertyName, valueType);
	}
	

	
	// not recommended
	// mainly for debug
	// return the first Property with the specified name
	public Property getProperty (String propertyName)
	{
		for ( int i = mPropertyGroups.size() - 1; i >= 0; -- i )
		{
			Property property = mPropertyGroups.elementAt (i).getProperty (propertyName, false);
			if ( property != null )
				return property;
		}
		
		logger.warn ("Property [" + propertyName + "] doesn't exist at all.");
		
		return null;
	}

	// not recommended
	// mainly for debug
	public Property removeProperty (String propertyName)
	{
		for ( int i = mPropertyGroups.size() - 1; i >= 0; --i )
		{
			Property property = mPropertyGroups.elementAt (i).removeProperty (propertyName);
			if ( property != null )
				return property;
		}
		
		logger.warn ("Nothing is remove, for Property [" + propertyName + "] doesn't exist at all.");	
		return null;
	}

	
//---------------------------------------------------------------------------
	
	// for debug
	public void dump ()
	{
		logger.debug ("----------------- Property Dump ------------------------------");
		for ( int i = 0; i < mPropertyGroups.size(); ++ i )
		{
			mPropertyGroups.elementAt (i).dump ();			
		}
		logger.debug ("----------------- Dump End -----------------------------------");
	}
	
}



